home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
utility
/
dirsize.zip
/
DIRSIZE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-30
|
5KB
|
206 lines
/*
** DirSize
** by Flavio Stanchina
** Loc. Montevaccino n░ 39
** 38040 Trento (Italy)
** 2:333/408.9@fidonet.org
**
** This program is freeware. See the docs for more informations.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#if defined(__SASC)
#define _USEOLDEXEC_ // Don't use SysBase for exec.library calls
#include <proto/exec.h>
#include <proto/dos.h>
#endif
#include "DirSize_rev.h"
/***** Structure for passing data to/from DirSize() ****/
#define DSD_PAT_SIZE 256
struct DirSizeData {
LONG Files, Dirs;
LONG Bytes, Blocks;
TEXT Pattern[DSD_PAT_SIZE];
LONG BlockSize; // Data for GetDirSize
LONG Extension;
LONG DoAll; // Flags
LONG DoLinks;
};
static LONG GetDirSize(STRPTR, struct DirSizeData *);
/***** Libraries *****/
struct DosLibrary *DOSBase;
TEXT DOSName[] = DOSNAME;
/***** Strings *****/
TEXT Header[] = "DirSize" VERSTAG " by Flavio Stanchina";
TEXT FormatStr[] = "%ld files - %ld dirs - %ld bytes - %ld blocks\n";
TEXT Template[] = "DIR,P=PATTERN,BS=BLOCKSIZE/N,EXT=EXTENSION/N,ALL/S,LINKS/S";
enum ARG_INDEX { ARG_DIR, ARG_PAT, ARG_BS, ARG_EXT, ARG_ALL, ARG_LNK, ARG_COUNT };
/***** Program entry point (no startup code) *****/
LONG __saveds Main(void)
{
struct DirSizeData *dsd;
struct RDArgs *rda;
APTR args[ARG_COUNT];
LONG rc = RETURN_FAIL; // let's be pessimistic
if(DOSBase = (struct DosLibrary *)OpenLibrary(DOSName, 37))
{
if(dsd = AllocMem(sizeof(struct DirSizeData), MEMF_CLEAR))
{
rc = RETURN_ERROR; // things are getting better
/*
** Just a quick note on the following assignment...
**
** We're telling ReadArgs that our default directory is the current one, and
** the way to do that is making the argument point to an empty string. You
** might think that a null pointer would do, and you are half right, because
** location zero always contains zero (except if you own some bugged versions
** of the A590/A2091 ROMs), so the string starting at location zero can be
** thought of as an empty string.
**
** But if you were running _The Enforcer_, it would report a read hit on
** location zero, so we supply our own empty string to settle the question
** once and for all.
*/
args[ARG_DIR] = ""; // Means "current directory"
args[ARG_PAT] = NULL;
args[ARG_BS ] = NULL;
args[ARG_EXT] = NULL;
args[ARG_ALL] = FALSE;
args[ARG_LNK] = FALSE;
if(rda = ReadArgs(Template, (LONG *)args, NULL))
{
if(args[ARG_PAT])
if(ParsePatternNoCase((STRPTR)args[ARG_PAT], dsd->Pattern, DSD_PAT_SIZE) <= 0)
{
PutStr("Ignoring wrong pattern\n");
dsd->Pattern[0] = '\0';
}
dsd->BlockSize = args[ARG_BS ] ? *(LONG *)args[ARG_BS ] : 512;
dsd->Extension = args[ARG_EXT] ? *(LONG *)args[ARG_EXT] : 72;
dsd->DoAll = (LONG)args[ARG_ALL];
dsd->DoLinks = (LONG)args[ARG_LNK];
if((dsd->BlockSize >= 8) || (dsd->Extension >= 0))
{
LONG result2;
if(result2 = GetDirSize((STRPTR)args[ARG_DIR], dsd))
{
PrintFault(result2, Header);
rc = RETURN_WARN;
}
else rc = RETURN_OK; // we're lucky today
VPrintf(FormatStr, (LONG *)dsd);
}
else PrintFault(ERROR_BAD_NUMBER, Header);
FreeArgs(rda);
}
else PrintFault(IoErr(), Header);
FreeMem(dsd, sizeof(struct DirSizeData));
}
else PrintFault(ERROR_NO_FREE_STORE, Header);
CloseLibrary((struct Library *)DOSBase);
}
return(rc);
}
/***** Reads the directory *****/
// Returns zero if ok, or DOS error code if something went wrong.
static LONG GetDirSize(STRPTR name, struct DirSizeData *dsd)
{
BPTR lock, oldCD;
struct FileInfoBlock *fib;
LONG temp;
LONG rc;
/* Set up some things */
if(fib = AllocDosObject(DOS_FIB, NULL))
{
if(lock = Lock(name, ACCESS_READ))
{
oldCD = CurrentDir(lock);
if(Examine(lock, fib))
{
while(ExNext(lock, fib))
{
if(fib->fib_DirEntryType < 0) // It's a file...
{
/* Let's see if this file is to be included... */
if(dsd->Pattern[0])
if(!MatchPatternNoCase(dsd->Pattern, fib->fib_FileName))
{
if(IoErr() == ERROR_TOO_MANY_LEVELS) break;
else continue;
}
/* Update our counts */
dsd->Files += 1;
if((fib->fib_DirEntryType != ST_LINKFILE) || dsd->DoLinks)
{
dsd->Bytes += fib->fib_Size;
if(fib->fib_Size)
{
// Data blocks
temp = (fib->fib_Size + dsd->BlockSize - 1) / dsd->BlockSize;
if(dsd->Extension)
// Header + extension blocks
temp += (temp + dsd->Extension - 1) / dsd->Extension;
}
else temp = 1; // A zero length file requires an header
dsd->Blocks += temp;
}
else dsd->Blocks += 1;
} else {
dsd->Dirs += 1;
dsd->Blocks += 1;
if(dsd->DoAll && ((fib->fib_DirEntryType != ST_LINKDIR) || dsd->DoLinks))
if(rc = GetDirSize(fib->fib_FileName, dsd)) goto error;
}
}
if((rc = IoErr()) == ERROR_NO_MORE_ENTRIES) rc = 0;
}
else rc = IoErr();
error:
CurrentDir(oldCD);
UnLock(lock);
}
else rc = IoErr();
FreeDosObject(DOS_FIB, fib);
}
else rc = ERROR_NO_FREE_STORE;
return(rc);
}